/**
 * Created by Administrator on 2017/5/8.
 */

// Create interfaces using a pre-defined Interface
// constructor that accepts an interface name and
// skeleton methods to expose.
// In our reminder example summary() and placeOrder()
// represent functionality the interface should
// support
var reminder = new Interface("List", ["summary", "placeOrder"]);

function Interface(name,methods) {
    if(arguments.length!=2){
        throw new Error("定义接口的参数个数错误！");
    }
    this.name = name;
    this.methods = [];
    for(var i=0;i<methods.length;i++){
        if(typeof methods[i] != "string"){
            throw  new Error(this.name + "接口中方法定义有误！");
        }
        this.methods.push(methods[i]);
    }
}

Interface.ensureImplements=function (object,interfaces) {
    if(arguments.length != 2){
        throw new Error("Interface.ensureImplements方法参数个数错误！");
    }
    if(!object instanceof  Object){
        throw new Error("Interface.ensureImplements第一个参数必须为Object实例！");
    }
    if(Object.prototype.toString.call(interfaces)!="[object Array]"){
        throw new Error("Interface.ensureImplements第二个参数必须为接口组！");
    }
    for(var i=0;i<interfaces.length;i++){
        var interface = interfaces[i];
        if(!(interface instanceof  Interface)){
            throw new Error("Interface.ensureImplements第二个参数中对象必须为Interface实例");
        }
        for(var j=0;j<interface.methods.length;j++){
            var method=interface.methods[j];
            if(!object[method] || typeof object[method] != "function"){
                throw new Error("接口中的"+method+"方法未被实现!");
            }
        }
    }
}

// Now create a constructor implementing the above properties
// and methods
function Todo(config) {
// State the methods we expect to be supported
// as well as the Interface instance being checked
// against
    Interface.ensureImplements(config.actions, [reminder]);
    this.name = config.name;
    this.methods = config.actions;
}

var properties = {
    name: "Remember to buy the milk",
    date: "05/06/2016",
    actions: {
        summary: function () {
            return "Remember to buy the milk, we are almost out!";
        },
        placeOrder: function () {
            return "Ordering milk from your local grocery store";
        }
    }
};
// Create a new instance of our Todo constructor
var todoItem = Todo(properties);
// Finally test to make sure these function correctly
console.log(todoItem.methods.summary());
console.log(todoItem.methods.placeOrder());
// Outputs:
// Remember to buy the milk, we are almost out!
// Ordering milk from your local grocery store